package com.gitee.huanminabc.utils_tools.jdbc_extend.jdbc;


import com.alibaba.fastjson.JSON;
import com.gitee.huanminabc.utils_tools.jdbc_extend.jdbc.transaction.JdbTransaction;
import com.zaxxer.hikari.HikariDataSource;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.sql.*;
import java.util.*;

//不使用连接池
@Slf4j
public class JdbcUtil implements  AutoCloseable{
    private final HikariDataSource druidDataSource;
    @SneakyThrows
    public JdbcUtil(String url, String username, String password, String driverClassName) {
        HikariDataSource druidDataSource = new HikariDataSource();
        druidDataSource.setUsername(username);
        druidDataSource.setPassword(password);
        druidDataSource.setJdbcUrl(url);
        druidDataSource.setDriverClassName(driverClassName);
        druidDataSource.setConnectionTimeout(10000);
        this.druidDataSource = druidDataSource;

    }

    @SneakyThrows
    public Connection getConnection() {
        //注册Driver驱动
       return druidDataSource.getConnection();
    }


    public<T> T queryEntity(Class<T> tClass,String sql, Object... args)  {
        Map<String, Object> query = query(sql, args);
        //将map转为实体类
        String jsonString = JSON.toJSONString(query);
        return JSON.parseObject(jsonString,tClass);
    }

    //sql: select * from user where id=? and name=?
    // args: 1, "张三"
    @SneakyThrows
    public Map<String, Object> query(String sql, Object... args)  {
        Map<String, Object> map = new HashMap<>(30);
        try (
                 PreparedStatement preparedStatement = getConnection().prepareStatement(sql);
                 ResultSet resultSet = preparedStatement.executeQuery();
            ){
            for (int i = 1; i <= args.length; i++) {
                preparedStatement.setObject(i, args[i - 1]);
            }
            ResultSetMetaData rsmd = resultSet.getMetaData();
            int columnsNumber = rsmd.getColumnCount();

            if (resultSet.next()) {
                for (int i = 1; i <= columnsNumber; i++) {
                    map.put(rsmd.getColumnName(i), resultSet.getObject(i));
                }
            }
        }
        return map;
    }

    public List<Map<String, Object>> querys(String sql, Object... args) {
        Connection connection = getConnection();
        return querys(connection, sql, args);
    }

    @SneakyThrows
    public static List<Map<String, Object>> querys(Connection connection, String sql, Object... args) {
        List<Map<String, Object>> maps;
        try(
                PreparedStatement preparedStatement = connection.prepareStatement(sql);
                ResultSet resultSet = preparedStatement.executeQuery();
        ) {

            for (int i = 1; i <= args.length; i++) {
                preparedStatement.setObject(i, args[i - 1]);
            }
            maps = dataGroup(resultSet);
        }
        return maps;
    }


    public static List<Map<String, Object>> dataGroup(ResultSet resultSet) throws SQLException {
        List<Map<String, Object>> maps = new ArrayList<>(1000);
        ResultSetMetaData rsmd = resultSet.getMetaData();
        int columnsNumber = rsmd.getColumnCount();
        while (resultSet.next()) {
            Map<String, Object> map = new HashMap<>(30);
            for (int i = 1; i <= columnsNumber; i++) {
                map.put(rsmd.getColumnName(i), resultSet.getObject(i));
            }
            maps.add(map);
        }
        resultSet.close();
        return maps;
    }


    //增删改
    public int execute(String sql, Object... args) {
        Connection connection = getConnection();
        return execute(connection, sql, args);
    }

    @SneakyThrows
    public static int execute(Connection connection , String sql, Object... args) {
        int i1 = 0;
        try (
                PreparedStatement preparedStatement =connection.prepareStatement(sql);
            ){

            for (int i = 1; i <= args.length; i++) {
                preparedStatement.setObject(i, args[i - 1]);
            }
            i1 = preparedStatement.executeUpdate();
        }
        return i1;
    }


    //继承JdbcBusTask接口实现run方法
    @SneakyThrows
    public  boolean transaction(JdbTransaction jdbTransaction) {
        Connection connection = getConnection();
        try {
            //开启事物
            connection.setAutoCommit(false);
            jdbTransaction.run(connection);
            //提交事物
            connection.commit();
            return true;
        } catch (Exception e) {
            log.error("",e);
            //回滚事物
            connection.rollback();
        } finally {
            //关闭事物
            connection.setAutoCommit(true);
        }
        return false;
    }





    @Override
    public void close() throws Exception {
        //关闭连接池
        this.druidDataSource.close();
    }
}
